package org.ccay.excel.util.impl;

import java.io.File;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

import javax.xml.stream.XMLStreamException;

import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.ccay.core.exception.ApplicationException;
import org.ccay.core.exception.impl.ExceptionMessageManager;
import org.ccay.core.ioc.Ccay;
import org.ccay.core.ioc.CcayApplicationContext;
import org.ccay.core.log.CcayLoggerFactory;
import org.ccay.core.log.ILogger;
import org.ccay.core.util.DateUtil;
import org.ccay.core.util.PathUtil;
import org.ccay.core.util.StreamUtil;
import org.ccay.core.util.StringUtil;
import org.ccay.excel.exception.ExcelApplicationException;
import org.ccay.excel.exception.ExcelExportConstants;
import org.ccay.excel.exception.ExcelExportException;
import org.ccay.excel.exception.ExcelImportException;
import org.ccay.excel.exporter.IExcelExportSupport;
import org.ccay.excel.importer.ExcelImportConstants;
import org.ccay.excel.importer.IExcelImportProcessBefore;
import org.ccay.excel.importer.service.IExcelImportSupport;
import org.ccay.excel.importer.service.impl.internal.ExcelMetaParser;
import org.ccay.excel.meta.ExcelMeta;
import org.ccay.excel.meta.IExcelSupportFinder;
import org.ccay.registry.util.RegistryQueryUtil;
import org.ccay.security.util.SecurityUtil;
import org.ccay.vfs.VFS;
import org.xml.sax.InputSource;

/**
 * excel 导入导出权限验证
 * 
 * @author chaowangbang
 * 
 */
public final class ExcelUtil {
	
	/**
	 * 虚拟文件系统 模块名称
	 */
	public static final String VFS_MODULE_EXCEL = "excel";
	
	
	/**
	 * 日期格式
	 */
	private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");

	/**
	 * 日志记录器
	 */
	private static ILogger logger = CcayLoggerFactory.getLogger(ExcelUtil.class);

	/**
	 * 避免创建实例
	 */
	private ExcelUtil() {
		
	}
	
	public static boolean validatePrivilege(String privilege) {
		return SecurityUtil.checkPermissionNoThrowsException(privilege);
	}

	/**
	 * 获取导出支持Bean
	 * 
	 * @param excelType
	 * @return
	 * @throws ApplicationException 
	 */
	public static IExcelExportSupport getExportSupport(String excelType) throws ApplicationException {
		CcayApplicationContext app = Ccay.getContext();
		Map<String,IExcelSupportFinder> finderMap = app.getBeansOfType(IExcelSupportFinder.class);
		if(finderMap !=null && finderMap.values()!=null){
			for (IExcelSupportFinder finder : finderMap.values()) {
				//如果符合其他的导出 那么执行 否则使用框架默认导出
				if(finder.support(excelType)){
					return finder.getExportSupport(excelType);
				}
			}
		}	
		try {
			return app.getBean("IExcelExportSupport." + excelType, IExcelExportSupport.class);
		} catch (Exception t) {
			// 异常:没有找到excelType对应的IExcelExportSupport实现，请检查excelType.excelExport.xml文件是否存在？
			logger.error(t);
			throw new ExcelExportException(ExcelExportConstants.ExcelExportSupport_NOT_FOUND, t, excelType);
		}
	}

	/**
	 * 获取导入支持Bean
	 * 
	 * @param excelType
	 * @return
	 */
	public static IExcelImportSupport getImportSupport(String excelType) throws ApplicationException {
		CcayApplicationContext app = Ccay.getContext();
		Map<String,IExcelSupportFinder> finderMap = app.getBeansOfType(IExcelSupportFinder.class);
		if(finderMap !=null && finderMap.values()!=null){
			for (IExcelSupportFinder finder : finderMap.values()) {
				//如果符合其他的导出 那么执行 否则使用框架默认导出
				if(finder.support(excelType)){
					return finder.getImportSupport(excelType);
				}
			}
		}
		try {
			return app.getBean("IExcelImportSupport." + excelType, IExcelImportSupport.class);
		} catch (Exception t) {
			// 异常:没有找到excelType对应的IExcelImportSupport实现，请检查excelType.excelExport.xml文件是否存在？
			logger.error(t);
			throw new ExcelImportException(ExcelImportConstants.ExcelImportSupport_NOT_FOUND, t, excelType);
		}
	}

	/**
	 * 获取解析excel的前置bean
	 * 
	 * @param excelType
	 * @return
	 */
	public static IExcelImportProcessBefore getImportProcessBefore(String beanName) throws ExcelImportException {
		if (StringUtil.isNullOrEmpty(beanName)) {
			return null;
		}
		CcayApplicationContext app = Ccay.getContext();
		try {
			return app.getBean("IExcelImportProcessBefore." + beanName, IExcelImportProcessBefore.class);
		} catch (Exception t) {
			// 异常:没有找到
			logger.error(t);
			throw new ExcelImportException(ExcelImportConstants.EXCEL_IMPORT_PROCESS_BEFORE_NOT_FOUND, t, beanName);
		}
	}

	/**
	 * 获取导出的文件路径 并生成目录
	 * 
	 * @return exportFilePath
	 */
	public static String buildExportFilePath(String excelType) {
		return excelType+"/"+ DATE_FORMAT.format(new Date());
	}

	/**
	 * 获取导出的文件名称
	 * 
	 * @return
	 */
	public static String buildExportFileName(String fileName) {
		// 获取文件名称
		String exportFileName = fileName + DateUtil.date24ToNumberString(new Date());
		return exportFileName;
	}

	/**
	 * 获取导出到服务器的文件路径和文件名称
	 * 
	 * @return
	 */
	public static String buildExportFileStore(String excelType) {
		// 获取文件路径
		return MessageFormat.format("{0}/{1}.xlsx", buildExportFilePath(excelType), UUID.randomUUID().toString());
	}

	/**
	 * 获取导出到服务器的文件路径和文件名称
	 * 
	 * @return
	 */
	public static String buildExportFileStore(String excelType, String type) {
		// 获取文件路径
		return MessageFormat.format("{0}/{1}." + type, buildExportFilePath(excelType), UUID.randomUUID().toString());
	}

	/**
	 * 构造一个安全的提示信息
	 * 
	 * @param t
	 *            异常
	 * @param lang
	 *            语种
	 * @return Created：2012-9-7
	 * @author chaowangbang
	 */
	public static String buildErrorMsg4Security(Throwable t) {
		if (t instanceof ApplicationException) {
			return t.getMessage();
		}
		return ExceptionMessageManager.getSystemErrorMessage();
	}

	/**
	 * 构造一个安全的提示信息
	 * 
	 * @param t
	 *            异常
	 * @param lang
	 *            语种
	 * @return Created：2012-9-7
	 * @author chaowangbang
	 */
	public static String buildErrorMsg4File() {
		return ExceptionMessageManager.getMessage("ccay.excel.00080005");
	}

	/**
	 * ExcelMeta解析器
	 */
	private static final ExcelMetaParser exelMetaParser = new ExcelMetaParser();

	// 异常编码
	private static final String GENERATETEMPLATE_EXCEPTION = "ccay.excel.00080002";

	/**
	 * 根据输入流解析元数据
	 * 
	 * @param is
	 * @return
	 * @throws ApplicationException
	 * @throws XMLStreamException
	 */
	public static ExcelMeta getExcelMetaByStream(InputStream is) throws ApplicationException {
		return getExcelMetaBySorce(new InputSource(is));
	}

	/**
	 * 根据输入流解析元数据
	 * 
	 * @param meta
	 * @return
	 * @throws ApplicationException
	 * @throws XMLStreamException
	 */
	public static ExcelMeta getExcelMetaByString(String meta) throws ApplicationException {
		Reader is = new StringReader(meta);
		try {
			return getExcelMetaBySorce(new InputSource(is));
		} finally {
			StreamUtil.closeStreams(is);
		}
	}

	/**
	 * 根据输入流解析元数据
	 * 
	 * @param is
	 * @return
	 * @throws ApplicationException
	 * @throws XMLStreamException
	 */
	public static ExcelMeta getExcelMetaBySorce(InputSource inputSource) throws ApplicationException {
		try {
			ExcelMeta excelMeta = exelMetaParser.parse(inputSource);
			if (excelMeta == null) {
				throw new ExcelApplicationException(GENERATETEMPLATE_EXCEPTION);
			}
			return excelMeta;
		} catch (XMLStreamException e) {
			// 解析失败抛出异常
			throw new ExcelApplicationException(GENERATETEMPLATE_EXCEPTION, e);
		}
	}
	
	/**
	 * 获取excel列标题颜色
	 * @return
	 */
	public static short getForegroundColorIndex(IndexedColors defaultIndexedColor){
		IndexedColors defaultColor = defaultIndexedColor;
		if(defaultIndexedColor == null){
			defaultColor = IndexedColors.LIGHT_YELLOW;
		}
		//获取excel列标题颜色
		String registryValue = RegistryQueryUtil.getValue(ExcelImportConstants.FOREGROUND_COLOR_PATH);
		if(defaultColor.name().equals(registryValue)){
			return defaultColor.getIndex();
		}
		IndexedColors customerColor = null;
		try{
			customerColor = IndexedColors.valueOf(registryValue);
		}catch (IllegalArgumentException e) {
			//若数据字典中ForegroundColor配置错误，给默认颜色
			logger.error("Ccay.Excel.ForegroundColor is error!", e);
			customerColor = defaultColor;
		}
		return customerColor.getIndex();
	}
	
	/** 
	 * 创建sheet页,增加判断,避免临时文件删除的问题
	 * @author chaowangbang
	 * @since 2016年4月22日
	 * @param workbook
	 * @param sheetName
	 */
	public static Sheet creatSheet(Workbook workbook, String sheetName) {
		File file = new File(System.getProperty("java.io.tmpdir"), "poifiles");
		if (!file.exists()) {
			file.mkdirs();
		}
		return workbook.createSheet(sheetName);
	}
	

}
